// 使用 try、on 以及 catch 关键字来处理异常：
breedMoreLlamas() {}
buyMoreLlamas() {}
cleanLlamaStalls() {}

class OutOfLlamasException {}

// on 处理特定异常
// 要执行一段无论是否抛出异常都会执行的代码，请使用 finally：
someFunction() {
  try {
    breedMoreLlamas();
  } on OutOfLlamasException {
    // A specific exception
    buyMoreLlamas();
  } on Exception catch (e) {
    // Anything else that is an exception
    print('Unknown exception: $e');
  } catch (e) {
    // No specified type, handles all
    print('Something really unknown: $e');

    // 如果你无法完全处理该异常，请使用 rethrow 关键字再次抛出异常：
    rethrow;
  } finally {
    // Always clean up, even if an exception is thrown.
    cleanLlamaStalls();
  }
}

// 在下面实现 tryFunction() 方法。它应该会执行一个不可靠的方法，然后做以下操作：
// 如果 untrustworthy() 抛出了 ExceptionWithMessage，则调用 logger.logException 并传入使用异常类型和消息（尝试使用 on 和 catch）。
// 如果 untrustworthy() 抛出了一个 Exception，则调用 logger.logException 并传入使用异常类型（这次请尝试使用 on）。
// 如果 untrustworthy() 抛出了其他对象，请不要捕获该异常。
// 捕获并处理完所有内容后，调用 logger.doneLogging（尝试使用 finally）。
typedef VoidFunction = void Function();

class ExceptionWithMessage {
  final String message;
  const ExceptionWithMessage(this.message);
}

// Call logException to log an exception, and doneLogging when finished.
abstract class Logger {
  void logException(Type t, [String? msg]);
  void doneLogging();
}

class LogClass extends Logger {
  logException(Type t, [String? msg]) {
    print('handled:$msg');
  }

  doneLogging() {
    print("done!");
  }
}

untrustworthyFn() {
  throw ExceptionWithMessage('11111!');
  // throw 'Waaaaaaah!';
}

void tryFunction(VoidFunction untrustworthy, Logger logger) {
  // Invoking this method might cause an exception. Catch and handle
  // them using try-on-catch-finally.
  try {
    untrustworthy();
  } on ExceptionWithMessage catch (e) {
    // A specific exception
    logger.logException(ExceptionWithMessage, e.message);
  } on Exception {
    logger.logException(Exception);
  } finally {
    // Always clean up, even if an exception is thrown.
    logger.doneLogging();
  }
}

main(List<String> args) {
  // throw Exception('Something bad happened.');
  // throw 'Waaaaaaah!';
  // someFunction();

  tryFunction(untrustworthyFn, LogClass());
}
